package main

import (
	"context"
	"fmt"
	"google.golang.org/grpc"
	"io"
	"log"
	pb "protoc-demo02/proto"
	"time"
)

// 引入生成的proto
func main() {
	//conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure(), grpc.WithBlock())
	conn, err := grpc.NewClient("localhost:50051", grpc.WithInsecure())
	if err != nil {
		log.Fatalf("did not connect: %v", err)
	}
	// 下面这个如果不加defer就会报：could not greet: rpc error: code = Canceled desc = grpc: the client connection is closing
	//defer conn.Close()
	defer func(conn *grpc.ClientConn) {
		_ = conn.Close()
	}(conn)
	c := pb.NewSumServiceClient(conn)

	ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
	defer cancel()
	fmt.Println()
	fmt.Println("--------------调用Sum方法--------------")
	fmt.Println()
	// 调用服务端的Sum方法 SumRequest同理是.proto定义message的变体
	r, err := c.Sum(ctx, &pb.SumRequest{A: 3, B: 5})
	if err != nil {
		log.Fatalf("could not greet: %v", err)
	}
	log.Printf("Sum: %d", r.Result)

	fmt.Println()
	fmt.Println("--------------调用Subtract方法--------------")
	fmt.Println()
	// 调用Subtract方法
	// 注意r和r1类型不同 所以要区分开
	r1, err := c.Subtract(ctx, &pb.SubtractRequest{A: r.Result, B: 5})
	if err != nil {
		log.Fatalf("could not greet: %v", err)
	}
	log.Printf("Subtract: %d", r1.Result)

	fmt.Println()
	fmt.Println("--------------调用Factor方法--------------")
	fmt.Println()
	// 调用Factor方法
	// 先获取stream
	stream, err := c.Factors(ctx, &pb.FactorsRequest{Num: 12})
	if err != nil {
		log.Fatalf("could not greet: %v", err)
	}
	for {
		// 然后Recv()
		factor, err := stream.Recv()
		// 接收流时 根据err判断是否结束
		if err == io.EOF {
			break
		}
		if err != nil {
			log.Fatalf("%v.Factors(_) = _, %v", c, err)
		}
		log.Println(factor)
	}

	fmt.Println()
	fmt.Println("--------------调用SumStream方法--------------")
	fmt.Println()
	// 调用SumStream方法
	// 这里stream和stream1类型不同 所以要区分开
	stream1, err := c.SumStream(ctx)
	if err != nil {
		log.Fatalf("could not greet: %v", err)
	}
	// 先发送数据
	for _, num := range []int32{1, 2, 3, 4, 5} {
		if err := stream1.Send(&pb.SumStreamRequest{Num: num}); err != nil {
			log.Fatalf("%v.Send(%v) = %v", stream1, num, err)
		}
	}
	// 然后调用CloseAndRecv()获取结果
	res, err := stream1.CloseAndRecv()
	if err != nil {
		log.Fatalf("%v.CloseAndRecv() got error %v, want %v", stream, err, nil)
	}
	log.Printf("Sum: %d", res.Sum)
}
